﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Laby
{
    class Maze
    {
        public Cell[,] Laby { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }

        public Maze(int width, int height)
        {
            Width = width;
            Height = height;
            Laby = new Cell[width, height];
        }

        public void InitializeLaby()
        {
            for (int i = 0; i < Width; i++)
                for (int j = 0; j < Height; j++)
                    Laby[i, j] = new Cell();
        }

        bool IsInBounds(int xiatania, int youmu)
        {
            return xiatania >= 0 && xiatania < Width && youmu >= 0 && youmu < Height;
        }

        public void InitializeNeighbors()
        {
            for (int i = 0; i < Width; i++)
                for (int j = 0; j < Height; j++)
                {
                    if (IsInBounds(i - 1, j))
                        Laby[i, j].AddNeighbors(Laby[i - 1, j]);
                    if (IsInBounds(i + 1, j))
                        Laby[i, j].AddNeighbors(Laby[i + 1, j]);
                    if (IsInBounds(i, j - 1))
                        Laby[i, j].AddNeighbors(Laby[i, j - 1]);
                    if (IsInBounds(i, j + 1))
                        Laby[i, j].AddNeighbors(Laby[i, j + 1]);
                }
        }

        public void Print()
        {
            Console.Write(".");

            for (int i = 0; i < Height; i++)
                Console.Write("_.");

            Console.Write("\n");

            for (int i = 0; i < Width; i++)
            {
                Console.Write("|");
                for (int j = 0; j < Height; j++)
                {
                    if (i + 1 < Laby.GetLength(0) && Laby[i, j].IsLinked(Laby[i + 1, j]))
                        Console.Write(" ");
                    else
                        Console.Write("_");

                    if (j + 1 < Laby.GetLength(1) && Laby[i, j].IsLinked(Laby[i, j + 1]))
                        Console.Write(".");
                    else
                        Console.Write("|");
                }
                Console.WriteLine();
            }
        }

        public void GenerateLaby()
        {
            Random rnd = new Random();
            int x = rnd.Next(Width - 1);
            int y = rnd.Next(Height - 1);
            Cell c = Laby[x, y];
            Generate(c, rnd);
        }

        public void Generate(Cell c, Random rnd)
        {
            c.IsVisited = true;
            c.randomizeNeighbors(rnd);
            foreach (Cell c2 in c.Neighbors)
            {
                if (!c2.IsVisited)
                { 
                    c.AddLinked(c2);
                    c2.AddLinked(c);
                    Generate(c2, rnd);
                }
            } 
        }

        public List<Cell> SolveLaby()
        {
            for (int i = 0; i < Width; i++)
                for (int j = 0; j < Height; j++)
                    Laby[i, j].IsVisited = false;
            List<Cell> path = new List<Cell>();
            Solve(Laby[0, 0], Laby[Width - 1, Height - 1], path);
            path.Add(Laby[0, 0]);
            return path;
        }

        public bool Solve(Cell CStart, Cell CEnd, List<Cell> Path)
        {
            CStart.IsVisited = true;
            if (CStart == CEnd)
                return true;
            else
            {
                foreach (Cell c2 in CStart.Linked)
                    if (!c2.IsVisited)
                        if (Solve(c2, CEnd, Path))
                        {
                            Path.Add(c2);
                            return true;
                        }
                return false;
            }
        }


        public void Print(List<Cell> path)
        {
            Console.Write(" ___");
            for (uint j = 1; j < Laby.GetLength(1); j++)
                Console.Write(" ___");
            Console.WriteLine();

            for (int i = 0; i < Laby.GetLength(0); i++)
            {
                Console.Write("|");
                for (int j = 0; j < Laby.GetLength(1); j++)
                {
                    if (j + 1 < Laby.GetLength(1) && Laby[i, j].IsLinked(Laby[i, j + 1]))
                        Console.Write("    ");
                    else
                        Console.Write("   |");
                }
                Console.WriteLine();

                Console.Write("|");
                for (int j = 0; j < Laby.GetLength(1); j++)
                {
                    if (path.Contains(Laby[i, j]))
                        Console.Write(" X ");
                    else
                        Console.Write("   ");

                    if (j + 1 < Laby.GetLength(1) && Laby[i, j].IsLinked(Laby[i, j + 1]))
                        Console.Write(" ");
                    else
                        Console.Write("|");
                }
                Console.WriteLine();

                Console.Write("|");
                for (int j = 0; j < Laby.GetLength(1); j++)
                {
                    if (i + 1 < Laby.GetLength(0) && Laby[i, j].IsLinked(Laby[i + 1, j]))
                        Console.Write("   ");
                    else
                        Console.Write("___");

                    if (j + 1 < Laby.GetLength(1) && Laby[i, j].IsLinked(Laby[i, j + 1]))
                        Console.Write(" ");
                    else
                        Console.Write("|");
                }
                Console.WriteLine();
            }
        }
     }
}
